// 字典 wordList 中从单词 beginWord 和 endWord 的 转换序列 是一个按下述规格形成的序列
// beginWord -> s1 -> s2 -> ... -> sk：
//
//
// 每一对相邻的单词只差一个字母。
//
// 对于 1 <= i <= k 时，每个
// si 都在
// wordList 中。注意， beginWord 不需要在
// wordList 中。
//
// sk == endWord
//
//
// 给你两个单词 beginWord 和 endWord 和一个字典 wordList ，返回 从 beginWord 到 endWord 的 最短转换序列
//中的 单词数目 。如果不存在这样的转换序列，返回 0 。
//
// 示例 1：
//
//
//输入：beginWord = "hit", endWord = "cog", wordList = ["hot","dot","dog","lot","log","cog"]
//输出：5
//解释：一个最短转换序列是 "hit" -> "hot" -> "dot" -> "dog" -> "cog", 返回它的长度 5。
//
//
// 示例 2：
//
//
//输入：beginWord = "hit", endWord = "cog", wordList = ["hot","dot","dog","lot",
//"log"]
//输出：0
//解释：endWord "cog" 不在字典中，所以无法进行转换。
//
//
//
// 提示：
//
//
// 1 <= beginWord.length <= 10
// endWord.length == beginWord.length
// 1 <= wordList.length <= 5000
// wordList[i].length == beginWord.length
// beginWord、endWord 和 wordList[i] 由小写英文字母组成
// beginWord != endWord
// wordList 中的所有字符串 互不相同
//
//
// Related Topics 广度优先搜索 哈希表 字符串 👍 1256 👎 0


//leetcode submit region begin(Prohibit modification and deletion)
function ladderLength(beginWord: string, endWord: string, wordList: string[]): number {
    /*
    ? 把单词看作结点，由一个结点带出下一层的邻接点，用BFS去做。
    ? 维护一个队列，让起点词入列，level 为 1，然后出列考察。
    ? 将逐个字符变成26字母之一，看看是否在单词表，如果在，该新词为下一层的转换词。
    ? 将它入列，它的 level +1，并从单词表中删去这个词。
    ? 出列、入列…重复，当出列的单词和终点词相同，就遇到了终点词，返回它的 level。
    ? 当队列为空时，代表考察完所有词，始终没有遇到终点词，没有路径通往终点。


    ? 有一层抽象，将单词作为节点，如果两个单词可以互相转换，就是邻接关系，之间有一条无向边。
    ? 用图的 BFS 探索路径，求一点到另一点的最短路径，先遇到终点的路径最短。
     */
    const wordSet = new Set(wordList);
    const queue = [];
    queue.push([beginWord, 1]);

    while (queue.length) {
        const [word, level] = queue.shift();  //? 当前出列的单词
        //? 找到直接返回层级
        if (word == endWord) {
            return level;
        }
        //? 暴力查找下一个能转换的单词
        for (let i = 0; i < word.length; i++) { //? 遍历当前单词的所有字符
            for (let c = 97; c <= 122; c++) { //? 对应26个字母
                const newWord = word.slice(0, i) + String.fromCharCode(c) + word.slice(i + 1); //? 形成新词
                if (wordSet.has(newWord)) { //? 单词表里有这个新词
                    queue.push([newWord, level + 1]); //? 作为下一层的词入列
                    wordSet.delete(newWord);  //? 避免该词重复入列 这里核心逻辑是即使存在两条路 但两条路不管回不回交汇都不影响删除
                }
            }
        }
    }
    return 0; //? bfs结束，始终没有遇到终点

};
//leetcode submit region end(Prohibit modification and deletion)
